#! /usr/bin/env python
#
"""Utilities for caching computation results.
"""
__docformat__ = 'reStructuredText'


from time import time

from iterators cimport Iterator


## auxiliary classes

cdef class _TimeBasedUnique(Iterator):
    """Return a new unique ID at each iteration step.

    The returned ID is the number of nanoseconds elapsed since the
    system epoch.  The returned ID is guaranteed to be monotonically
    increasing::

      >>> u = _TimeBasedUnique()
      >>> u.next() < u.next() < u.next()
      True

    """
    def __next__(self):
        return int(time() * 1000000)

cdef _TimeBasedUnique _unique = _TimeBasedUnique()


cdef class Cacheable(object):
    """Instances of this class provide an interface for use by caches
    based on a `dict` subclass.
    """

    __slots__ = ['__id', '_cache']

    def __init__(self):
        self.__id = _unique.next()

    def cache_id(self):
        """Return a integer value which is unique and guaranteed not
        to be re-used.
        
        (In contrast, Python's standard `id()` function returns a
        value based on the intance memory address, which *can* be
        re-used during the lifetime of a program.)
        """
        return self.__id


cpdef cache_id(o):
    try:
        return o.cache_id()
    except AttributeError:
        return id(o)
